package main

import (
	"context"
	"fmt"
	"go.etcd.io/etcd/clientv3"
	"time"
)

func main() {
	config := clientv3.Config{
		Endpoints:   []string{"127.0.0.1:2379"},
		DialTimeout: 5 * time.Second,
	}

	client, err := clientv3.New(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	lease := clientv3.NewLease(client)
	grantResponse, err := lease.Grant(context.TODO(), 5)
	if err != nil {
		fmt.Println(err)
		return
	}
	leaseID := grantResponse.ID

	// lease实现锁自动过期
	ctx, cancel := context.WithCancel(context.TODO())
	defer cancel()
	defer lease.Revoke(context.TODO(), leaseID)

	// 自动续租
	keepAliveResponses, err := lease.KeepAlive(ctx, leaseID)
	if err != nil {
		fmt.Println(err)
		return
	}

	go func() {
		for {
			select {
			case res := <-keepAliveResponses:
				if res == nil {
					fmt.Println("租约已经失效了!")
					break
				} else {
					fmt.Println("收到续租的应答: ", leaseID)
				}
			}
		}
	}()

	// thx事务 抢锁
	kv := clientv3.NewKV(client)
	txn := kv.Txn(context.TODO())
	txn.If(clientv3.Compare(clientv3.CreateRevision("/cron/lock/job1"), "=", 0)).
		Then(clientv3.OpPut("/cron/lock/job1", "xxx", clientv3.WithLease(leaseID))).
		Else(clientv3.OpGet("/cron/lock/job1"))

	txnResponse, err := txn.Commit()
	if err != nil {
		fmt.Println(err)
		return
	}

	// 抢锁是否成功
	if !txnResponse.Succeeded {
		fmt.Println("锁被占用!", string(txnResponse.Responses[0].GetResponseRange().Kvs[0].Value))
		return
	}

	fmt.Println("处理业务...")
	time.Sleep(5 * time.Second)
}
